#!/usr/bin/env python2
import os
import sys
import errno
import uuid
import getopt
import subprocess
import time
import re
import ConfigParser
import fcntl

from utils import Exp, _dwarn, _exec_pipe, _put_remote, _exec_system, _exec_shell, _derror, \
                _isip, _exec_remote, _exec_pipe1

REMOTE_COPY_INTERVAL_DEFAULT = 60
REMOTE_COPY_THREAD_DEFAULT = 10
REMOTE_COPY_QOS_DEFAULT = 1
REMOTE_COPY_CACHE_DEFAULT = 1024

class Config():
    def __init__(self):
        path = os.path.abspath(os.path.split(os.path.realpath(__file__))[0])
        self.home = os.path.dirname(path)
        self.keep = 3
        self.root_path = '/opt/fusionstack/remotecopy'
        self.bin_path = '/usr/bin/'
        self.bin_name = 'lich.remotecopy'
        self.shm = '/dev/shm/lich4/remotecopy'
        self.prefix = 'lich_system_remotecopy'
        self.stat_path = os.path.join(self.home, 'stat')
        self.log_path = os.path.join(self.home, 'log')

        if not os.path.exists(self.shm):
            os.makedirs(self.shm)
        if not os.path.exists(self.stat_path):
            os.makedirs(self.stat_path)
        if not os.path.exists(self.log_path):
            os.makedirs(self.log_path)

    def get_conf(self, conf):
        self.config_path = os.path.join(self.home, 'etc/remotecopy_%s.conf' % conf)
        cf = ConfigParser.ConfigParser()
        cf.read(self.config_path)

        gloconf = {}
        server = {}
        client = {}

        secs = cf.sections()
        for sec in secs:
            sec_re = re.search('^[0-9a-z-_]+$', sec)
            if not sec_re:
                _dwarn("invalid '%s', only 'a-z', '0-9', '-', '_' is allowed" % sec)
                continue

            if sec == 'global':
                items = cf.items(sec)
                for item in items:
                    key = item[0]
                    value = item[1]
                    if key == 'thread' or key == 'qos' or key == 'cache' or key == 'interval':
                        try:
                            gloconf[key] = int(value)
                        except:
                            continue
                    elif key == 'stor':
                        user = value.split(':')[0]
                        host = value.split('@')[-1]
                        password = value[len(user) + 1:len(value)-len(host) - 1]
                        if not _isip(host):
                            raise Exp(errno.EINVAL, "%s %s(%s) is not ip in %s"
                                    %(sec, key, host, self.config_path))

                        gloconf[key] = {}
                        gloconf[key]['user'] = user
                        gloconf[key]['pass'] = password
                        gloconf[key]['host'] = host

            elif sec == 'server':
                items = cf.items(sec)
                keys = [x[0] for x in items]

                if len(items) == 0:
                    continue

                if 'listen' not in keys:
                    raise Exp(errno.EPERM, "section %s must config listen in %s" %(sec, self.config_path))

                for item in items:
                    key = item[0]
                    value = item[1]
                    if key == 'listen':
                        try:
                            port = int(value)
                        except:
                            raise Exp(errno.EINVAL, "%s %s(%s) is not valid in %s"
                                    %(sec, key, value, self.config_path))

                        server[key] = port
                    elif key == 'stor':
                        user = value.split(':')[0]
                        host = value.split('@')[-1]
                        password = value[len(user) + 1:len(value)-len(host) - 1]
                        if not _isip(host):
                            raise Exp(errno.EINVAL, "%s %s(%s) is not ip in %s"
                                    %(sec, key, host, self.config_path))

                        server[key] = {}
                        server[key]['user'] = user
                        server[key]['pass'] = password
                        server[key]['host'] = host
                    elif key == 'thread':
                        server[key] = int(value)
            else:
                items = cf.items(sec)
                keys = [x[0] for x in items]

                has_vol = False
                for key in keys:
                    if key == 'volume':
                        has_vol = True
                if not has_vol:
                    raise Exp(errno.EPERM, "section %s must config volume in %s" %(sec, self.config_path))
                if 'server' not in keys:
                    raise Exp(errno.EPERM, "section %s must config server in %s" %(sec, self.config_path))

                client[sec] = {}
                for item in items:
                    key = item[0]
                    value = item[1]
                    if key == 'server':
                        client[sec][key] = []
                        for i in value.split(','):
                            if ':' not in i:
                                continue
                            ip = i.split(':')[0]
                            if not _isip(ip):
                                raise Exp(errno.EINVAL, "%s %s(%s) is not ip in %s"
                                        %(sec, key, ip, self.config_path))
                            try:
                                port = int(i.split(':')[1])
                            except:
                                raise Exp(errno.EINVAL, "%s %s(%s) is not valid in %s"
                                        %(sec, key, port, self.config_path))
                            client[sec][key].append((ip, port))
                    elif key == 'volume':
                        client[sec][key] = []
                        for i in value.split(','):
                            if '@' in i:
                                vols = i.split('@')
                                client[sec][key].append((vols[0], vols[1]))
                            else:
                                client[sec][key].append((i, i))
                    elif key == 'interval':
                        try:
                            client[sec][key] = int(value)
                        except:
                            continue

        config = {}

        if 'thread' not in gloconf:
            gloconf['thread'] = REMOTE_COPY_THREAD_DEFAULT
        elif gloconf['thread'] < REMOTE_COPY_THREAD_DEFAULT:
            gloconf['thread'] = REMOTE_COPY_THREAD_DEFAULT
        if 'cache' not in gloconf:
            gloconf['cache'] = REMOTE_COPY_CACHE_DEFAULT
        if 'qos' not in gloconf:
            gloconf['qos'] = REMOTE_COPY_QOS_DEFAULT
        elif gloconf['qos'] > gloconf['cache']:
            gloconf['qos'] = gloconf['cache']
        if 'interval' not in gloconf:
            gloconf['interval'] = REMOTE_COPY_INTERVAL_DEFAULT
        elif gloconf['interval'] < REMOTE_COPY_INTERVAL_DEFAULT:
            gloconf['interval'] = REMOTE_COPY_INTERVAL_DEFAULT

        fd = open('/sys/class/dmi/id/product_uuid')
        gloconf['uuid'] = fd.read().strip()
        fd.close()

        for i in client:
            if 'interval' not in client[i]:
                client[i]['interval'] = gloconf['interval']
            elif client[i]['interval'] < REMOTE_COPY_INTERVAL_DEFAULT:
                client[i]['interval'] = REMOTE_COPY_INTERVAL_DEFAULT

        if len(server):
            if 'thread' not in server:
                server['thread'] = REMOTE_COPY_THREAD_DEFAULT
            else:
                if server['thread'] < REMOTE_COPY_THREAD_DEFAULT:
                    server['thread'] = REMOTE_COPY_THREAD_DEFAULT

        if conf == 'server': 
            config['server'] = server
        else:
            config['client'] = client
            config['global'] = gloconf

        return config
